//
//  Recorder.m
//  AudioQueueDemo
//
//  Created by marco on 16/3/8.
//  Copyright © 2016年 Marco. All rights reserved.
//

#import "Recorder.h"
#import "AQQueue.h"


NSString * const  g_kRecorderProcessAudioBuffer = @"g_kRecorderProcessAudioBuffer";

@interface Recorder()

@property (nonatomic,strong,readonly) NSMutableData* voiceData;
@property (nonatomic,strong) NSTimer *timer;
@property (nonatomic,assign) NSInteger time;

@end

@implementation Recorder


static void AQInputCallback (void                   * inUserData,
                             AudioQueueRef          inAudioQueue,
                             AudioQueueBufferRef    inBuffer,
                             const AudioTimeStamp   * inStartTime,
                             unsigned long          inNumPackets,
                             const AudioStreamPacketDescription * inPacketDesc)

{
    
    Recorder * engine = (__bridge Recorder *) inUserData;
    if (inNumPackets > 0)
    {
        [engine processAudioBuffer:inBuffer withQueue:inAudioQueue];
    }
    
    if (engine.aqc.run)
    {
        AudioQueueEnqueueBuffer(engine.aqc.queue, inBuffer, 0, NULL);
    }
    
}
//设置了播放和录音同时进行，注释掉的代码可以激活扬声器
-(void)initAudioSession
{
    
    AudioSessionInitialize(NULL, NULL, NULL, (__bridge void *)(self));
    
//    UInt32 route;
    OSStatus error;
    UInt32 sessionCategory = kAudioSessionCategory_PlayAndRecord;
    
    error = AudioSessionSetProperty (
                                     kAudioSessionProperty_AudioCategory,
                                     sizeof (sessionCategory),
                                     &sessionCategory
                                     );
    
//    route = kAudioSessionOverrideAudioRoute_Speaker;
//    error = AudioSessionSetProperty(kAudioSessionProperty_OverrideAudioRoute, sizeof(route), &route);
    AudioSessionSetActive(true);
    
}
- (id) initWithSampleRate:(NSInteger)pSampleRate
{
    self = [super init];
    if (self)
    {
        [self initAudioSession];
        
        _aqc.mDataFormat.mSampleRate = pSampleRate;
        _aqc.mDataFormat.mFormatID = kAudioFormatLinearPCM;
        _aqc.mDataFormat.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked;
        _aqc.mDataFormat.mFramesPerPacket = 1;
        _aqc.mDataFormat.mChannelsPerFrame = 1;
        _aqc.mDataFormat.mBitsPerChannel = 16;
        _aqc.mDataFormat.mBytesPerPacket = 2;
        _aqc.mDataFormat.mBytesPerFrame = 2;
        _aqc.frameSize = kFrameSize;
        _aqc.levels = (AudioQueueLevelMeterState *)calloc(sizeof(AudioQueueLevelMeterState), _aqc.mDataFormat.mChannelsPerFrame);
        UInt32 trueValue = true;
        AudioQueueSetProperty(_aqc.queue, kAudioQueueProperty_EnableLevelMetering, &trueValue, sizeof(UInt32));
        
        AudioQueueNewInput(&_aqc.mDataFormat, (AudioQueueInputCallback)AQInputCallback, (__bridge void * _Nullable)(self), NULL, kCFRunLoopCommonModes, 0, &_aqc.queue);
        
        _aqc.recPtr = 0;
        _aqc.run = 1;
        
        _voiceData = [NSMutableData new];
        
        AudioQueueStart(_aqc.queue, NULL);
//        int status = AudioQueueStart(_aqc.queue, NULL);
//        NSLog(@"AudioQueueStart = %d", status);
        
    }
    
    return self;
}

- (void)timerTick
{
    _time ++;
}


- (void) dealloc
{
    AudioQueueStop(_aqc.queue, true);
    
    _aqc.run = 0;
    
    AudioQueueDispose(_aqc.queue, true);
}

- (void) start
{
    AudioQueueStart(_aqc.queue, NULL);
    
    for (int i=0;i<kNumberBuffers;i++)
    {
        AudioQueueAllocateBuffer(_aqc.queue, (UInt32)_aqc.frameSize, &_aqc.mBuffers[i]);
        
        AudioQueueEnqueueBuffer(_aqc.queue, _aqc.mBuffers[i], 0, NULL);
    }
    UInt32 size = sizeof(UInt32) ;
    UInt32 enableLevelMetering = 1 ;
    
    AudioQueueSetProperty( _aqc.queue, kAudioQueueProperty_EnableLevelMetering, &enableLevelMetering, size ) ;
    if( _timer.valid )
    {
        [_timer invalidate];
    }
    _time = 0;
    _timer = [NSTimer timerWithTimeInterval:1.0f target:self selector:@selector(timerTick) userInfo:nil repeats:YES];
    [[NSRunLoop currentRunLoop] addTimer:_timer forMode:NSRunLoopCommonModes];
}

- (void) stop
{
    if( _timer.valid )
    {
        [_timer invalidate];
    }
    if( CONFIG_RECORDER_LOGIC_TYPE == CONFIG_RECORDER_LOGIC_TYPE_SEC )
    {
        [[NSNotificationCenter defaultCenter] postNotificationName:g_kRecorderProcessAudioBuffer object:_voiceData];
        _voiceData = [NSMutableData new];
        _time = 0;
    }
    AudioQueueStop(_aqc.queue, true);
}


- (void) pause
{
    AudioQueuePause(_aqc.queue);
}

- (void) processAudioBuffer:(AudioQueueBufferRef) buffer withQueue:(AudioQueueRef) queue
{
    
    long size = buffer->mAudioDataByteSize;
    
    t_sample * data = (t_sample *) buffer->mAudioData;
    
    NSData *codeData = [[NSData alloc] initWithBytes:data length:size];
    @synchronized(self.voiceDataQueue){
        [_voiceDataQueue enqueue:codeData];
        [self getPower:codeData];
    }
}

#pragma mark power
- (BOOL)isListening {
    if (self.aqc.queue == nil)
        return NO;
    
    UInt32 isListening, ioDataSize = sizeof(UInt32);
    OSStatus result = AudioQueueGetProperty(self.aqc.queue, kAudioQueueProperty_IsRunning, &isListening, &ioDataSize);
    return (result != noErr) ? NO : isListening;
}

- (AudioQueueLevelMeterState *)levels {
    if (![self isListening])
        return nil;
    
    [self updateLevels];
    return self.aqc.levels;
}

- (void)updateLevels {
    
    UInt32 ioDataSize = self.aqc.mDataFormat.mChannelsPerFrame * sizeof(AudioQueueLevelMeterState);
    AudioQueueGetProperty(self.aqc.queue, (AudioQueuePropertyID)kAudioQueueProperty_CurrentLevelMeter, self.aqc.levels, &ioDataSize);
}
- (Float32)peakPower {
    if (![self isListening])
        return 0.0;
    
    return [self levels][0].mPeakPower;
}

-(void)getPower:(NSData*)pData
{
    AudioQueueLevelMeterState *levels = [self levels];
    
    Float32 peak = 0;
    Float32 average = 0;
    if( levels )
    {
        peak = levels[0].mPeakPower; //音频通道的峰值均方根功率
        average = levels[0].mAveragePower; //音频信道的平均有效值功率
    }
    
    if( CONFIG_RECORDER_LOGIC_TYPE == CONFIG_RECORDER_LOGIC_TYPE_0_TO_0 )
    {
        if( _time > CONFIG_RECORDER_TO_ASR_INTERVAL )
        {
            if( _voiceData.length > 0 )
            {
                [[NSNotificationCenter defaultCenter] postNotificationName:g_kRecorderProcessAudioBuffer object:_voiceData];
                _voiceData = [NSMutableData new];
            }
            _time = 0;
        }
        else
        {
            if( peak > CONFIG_RECORDER_PEAKPOWER )
            {
                [_voiceData appendData:pData];
            }
            else
            {
                if( _voiceData.length > 0 )
                {
                    [[NSNotificationCenter defaultCenter] postNotificationName:g_kRecorderProcessAudioBuffer object:_voiceData];
                    _voiceData = [NSMutableData new];
                }
                _time = 0;
            }
        }
    }
    else if( CONFIG_RECORDER_LOGIC_TYPE == CONFIG_RECORDER_LOGIC_TYPE_SEC )
    {
        if( _time > CONFIG_RECORDER_TO_ASR_INTERVAL )
        {
            [[NSNotificationCenter defaultCenter] postNotificationName:g_kRecorderProcessAudioBuffer object:_voiceData];
            _voiceData = [NSMutableData new];
            _time = 0;
        }
        else
        {
            if( _voiceData.length <= 0 )
            {
                if(peak > 0.015)
                {
                    [_voiceData appendData:pData];
                }
                _time = 0;
            }
            else
            {
                [_voiceData appendData:pData];
            }
        }
    }
}


@end
